// 定义方式

// 一，限定普通对象
// 1.普通方式
interface NameInfo1 {
  firstName: string;
  lastName: string;
}

// 2.可选方式
interface NameInfo2 {
  firstName?: string; // 可选属性
  lastName: string;
}

// 3.多余属性（3种方式）
// 3.1 通过接口的 索引 签名 解决
interface NameInfo3 {
  firstName?: string;
  lastName: string;
  [props: string]: any; // props名字任意起， 这种属性 可以任意多个 可以 是函数
}

// 3.2 通过 断言方式 的 2种方式
// getFullName({ firstName: 'java', lastName: 'python' , num: 1} as NameInfo1);
// getFullName(<NameInfo1>{ firstName: 'java', lastName: 'python', num: 1 });

// 3.3 通过 类型兼容性
//  先定义 一个变量， 再将这个变量传入进去
// const veget= { firstName: 'java', lastName: 'python', num: 1 }
// getFullName(veget);

// 4.只读方式
interface NameInfo4 {
  firstName: string;
  readonly lastName: string; // 只读属性
}

// 用法
// 1.用于普通 对象 数据类型验证
const getFullName = ({ firstName, lastName }: NameInfo1): string => {
  return `${firstName}, ${lastName}`;
};
getFullName({ firstName: 'java', lastName: 'python' });

// 二.限定 数组(很少用)
// 2.1 定义方式
interface ArrInfo {
  0: number;
  readonly 1: string;
}
const arr: ArrInfo = [1, '2'];

// 三.限定 函数
// 下面两种写法都是一样的
// 方式1:
interface Func1 {
  (props: string): string;
}

// 方式2:tslint 推荐的写法 用类型别名
type Func2 = (props: string) => string;

// 使用：
const add: Func1 = n1 => n1;

// 四.限定 索引(很少用)
// 将这个 理解成 对象形式就行了
interface RoleDic {
  [i: number]: string;
}
// 使用
const role: RoleDic = {
  '0': '123',
  // 0: '123', 数字 也会转化成 0
};

// 五.接口继承
// 案例
// interface Vegetables {
//   color: string;
// }
// interface Tomato {
//   color: string;
//   radius: number;
// }
// interface Carrot {
//   color: string;
//   length: number;
// }

// 继承 优化后的
interface Vegetables {
  color: string;
}
interface Tomato extends Vegetables {
  radius: number;
}
interface Carrot extends Vegetables {
  length: number;
}

// 六.混合 类型 接口 定义
// 函数也是对象,

interface MixFuncStatic {
  (): void; // 普通函数的 定义
  count: number; // 函数 自身 的属性
}
